// Test file for Result class (TypeScript version)

// Import the Result class and related functions
import { Result, Ok, Err, From } from '../src/result'; // Replace with actual path

// Helper function for logging test results
function test(name: string, fn: () => void): void {
    try {
        fn();
        console.log(`✅ ${name} - PASSED`);
    } catch (error) {
        console.error(`❌ ${name} - FAILED:`, error instanceof Error ? error.message : String(error));
    }
}

// Test Ok creation
test('Ok creates successful result', () => {
    const result = Ok(42);
    if (!result.isOk) throw new Error('Expected isOk to be true');
    if (result.unwrap(0) !== 42) throw new Error('Expected value to be 42');
});

// Test Err creation
test('Err creates error result', () => {
    const result = Err('error message');
    if (result.isOk) throw new Error('Expected isOk to be false');
    if (result.unwrap('default') !== 'default') throw new Error('Expected default value');
});

// Test map on Ok
test('map transforms Ok value', () => {
    const result = Ok(2).map(x => x * 3);
    const a = result.unwrap(0)
    if (result.unwrap(0) !== 6) throw new Error('Expected mapped value to be 6');
});

// Test map with Result return
test('map can return new Result', () => {
    const result = Ok(2).map(x => Ok(x * 3));
    if (result.unwrap(0) !== 6) throw new Error('Expected nested Result with value 6');
});

// Test map on Err
test('map does nothing on Err', () => {
    const original = Err('error');
    const mapped = original.map((x: number) => x * 3);
    if (mapped.unwrap('default') !== 'default') throw new Error('Expected Err to remain unchanged');
});

// Test map with throwing function
test('map catches thrown errors', () => {
    const result = Ok(2).map(x => { throw new Error('test error'); });
    if (result.isOk) throw new Error('Expected error to be caught');
});

// Test andThen
test('andThen chains operations', () => {
    const result = Ok(2)
        .andThen(x => Ok(x * 3))
        .andThen(x => Ok(x + 1));
    if (result.unwrap(0) !== 7) throw new Error('Expected chained value to be 7');
});

// Test andThen with error
test('andThen preserves errors', () => {
    const result = Err('initial error')
        .andThen(x => Ok(x * 3));
    if (result.isOk) throw new Error('Expected error to be preserved');
});

// Test except
test('except handles errors', () => {
    const result = Err('error').except(err => 'recovered');
    if (!result.isOk) throw new Error('Expected recovery to succeed');
    if (result.unwrap('') !== 'recovered') throw new Error('Expected recovered value');
});

// Test except with Result return
test('except can return new Result', () => {
    const result = Err('error').except(err => Ok('recovered'));
    if (result.unwrap('') !== 'recovered') throw new Error('Expected nested Result with recovered value');
});

// Test From with successful function
test('From with successful function', () => {
    const result = From(() => 42);
    if (!result.isOk) throw new Error('Expected success');
    if (result.unwrap(0) !== 42) throw new Error('Expected value to be 42');
});

// Test From with successful function
test('From with successful function 11111111', async () => {
    const result:Promise<Result<number,any>,any> = From(async () => 42);
    if (await result.unwrap(0) !== 42) throw new Error('Expected value to be 42'+result.isOk +"");
});

// Test From with throwing function
test('From with throwing function', () => {
    const result = From(() => { throw new Error('test error'); });
    if (result.isOk) throw new Error('Expected error');
});

// Test Promise extensions
test('Promise map extension', async () => {
    const result = await From(async ()=>2).map(x => x * 3);
    console.log(result.isOk)
    if (result.unwrap(0) !== 6) throw new Error('Expected async mapped value to be 6');
});

test('Promise andThen extension', async () => {
    const result = await From(async ()=> Err(2)).andThen(x => Ok(x * 3));
    if (result.unwrap(0) !== 6) throw new Error('Expected async chained value to be 6');
});

test('Promise except extension', async () => {
    const result = await Err('error').toPromise().except(err => 'recovered');
    if (result.unwrap('') !== 'recovered') throw new Error('Expected async recovered value');
});

test('Promise unwrap extension', async () => {
    const value = await Ok(2).toPromise().unwrap(0);
    if (value !== 2) throw new Error('Expected async unwrapped value to be 2');
});

// Additional type safety tests
test('Type inference for Ok', () => {
    const result = Ok<string>('success');
    const value: string = result.unwrap('default');
    if (value !== 'success') throw new Error('Type inference failed for Ok');
});

test('Type inference for Err', () => {
    const result = Err<Error>(new Error('failure'));
    const value: string = result.unwrap('default');
    if (value !== 'default') throw new Error('Type inference failed for Err');
});

console.log('\nAll tests completed!');